Pinecone のベクトルデータベースをエミュレートできる Pinecone Local を試してみた

Pinecone のベクトルデータベースをエミュレートできる Pinecone Local を試してみた

Clock Icon2024.12.17

こんにちは!AWS 事業本部コンサルティング部のたかくに(@takakuni_)です。

ローカルで Pinecone のベクトルデータベースをエミュレートできる、 Pinecone Local というものが登場しました。

https://www.pinecone.io/blog/pinecone-local/

開発で役に立ちそうです。さっそく試してみましょう。

Pinecone Local

Pinecone Local は Docker イメージとして利用できる、 Pinecone Vector Database のエミュレーターです。

ローカルまたは CI/CD 環境にコンテナイメージを落としてきて利用します。

docker run -d \
--name pinecone-local \
-e PORT=5081 \
-e PINECONE_HOST=localhost
-p 5081-6000:5081-6000 \
--platform linux/amd64 \
ghcr.io/pinecone-io/pinecone-local:latest

Pinecone Local はインデックスあり、インデックスなしの 2 種類のコンテナイメージを提供しています。

すぐに試したい方向けにはインデックス有り、テストやインデックスを自分で管理したい場合はインデックス無しと使い分けが推奨されています。

  1. Start Pinecone Local
    You can configure Pinecone Local to start with or without indexes.
  • Starting with indexes is recommended for getting started with Pinecone Database or quickly experimenting with reading and writing data. This approach use the pinecone-index Docker image.
  • Starting without indexes is recommended for testing your production app or creating and managing indexes. This approach uses the pinecone-local Docker image.

https://docs.pinecone.io/guides/operations/local-development#1-start-pinecone-local

今回利用したコードは以下のとおりです。

https://github.com/takakuni-classmethod/genai-blog/tree/main/pinecone-local-overview

インデックス有り

まずはインデックス有りのコンテナを試してみます。いくつかパラメーターを指定するようです。

  • PORT: ポート番号
  • INDEX_TYPE: インデックスタイプ(serverless または pod を指定)
  • DIMENSION: 次元数
  • METRIC: 類似度を計算するためのメトリクス(cosine, euclidean, dotproduct のどれかを指定)
  • PORT: Specify the port number for the index to listen on.
  • INDEX_TYPE: Specify the type of Pinecone index to create. Accepted values: serverless or pod.
  • DIMENSION: Specify the dimension of vectors you will store in the index.
  • METRIC: Specify the distance metric for calculating the similarity between vectors in the index. Accepted values: cosine, euclidean, or dotproduct.

https://docs.pinecone.io/guides/operations/local-development#start-with-indexes

Docker Compose から立ち上げてみましょう。

docker-compose.yml
services:
  index1:
    image: ghcr.io/pinecone-io/pinecone-index:latest
    environment:
      PORT: 5081
      INDEX_TYPE: serverless
      DIMENSION: 1024
      METRIC: cosine
    ports:
      - '5081:5081'
    platform: linux/arm64

おっと怒られてしまいました。 ARM は対応していないみたいです。

takakuni@ pinecone-local-with-index % docker compose up -d
[+] Running 1/2
 ⠸ index1 [] 2.222MB / 2.222MB Pulling                                                                                                                                                                                                           20.4s593b926fe099 Pull complete                                                                                                                                                                                                                    4.8s
image with reference ghcr.io/pinecone-io/pinecone-index:latest was found but does not match the specified platform: wanted linux/arm64, actual: linux/amd64

amd64 で docker-compose を動かしてみます。

docker-compose.yml
services:
  index1:
    image: ghcr.io/pinecone-io/pinecone-index:latest
    environment:
      PORT: 5081
      INDEX_TYPE: serverless
      DIMENSION: 1024
      METRIC: cosine
    ports:
      - '5081:5081'
+    platform: linux/amd64

上手く動きましたね。

takakuni:~/environment $ docker compose up -d
[+] Running 2/2
 ✔ index1 Pulled                                                                                                                                                                                                                                                    1.5s593b926fe099 Pull complete                                                                                                                                                                                                                                     0.6s
[+] Running 2/2
 ✔ Network environment_default     Created                                                                                                                                                                                                                          0.1s
 ✔ Container environment-index1-1  Started

インデックス無し

インデックス無しの方も試してみましょう。5082 ポートもデータの登録で利用するため大きめに開けます。

docker-compose.yml
services:
  index1:
    image: ghcr.io/pinecone-io/pinecone-local:latest
    environment:
      PORT: 5081
      PINECONE_HOST: localhost
    ports:
      - '5081-6000:5081-6000'
    platform: linux/amd64

https://docs.pinecone.io/guides/operations/local-development#start-without-indexes

上手く動いていますね。

takakuni:~/environment $ docker compose up -d
[+] Running 2/2
 ✔ index1 Pulled                                                                                                                                                                                                                                                    1.6s3422d8f5b1d5 Pull complete                                                                                                                                                                                                                                     0.7s
[+] Running 2/2
 ✔ Network environment_default     Created                                                                                                                                                                                                                          0.1s
 ✔ Container environment-index1-1  Started

PineCone SDK でいくつか操作をしてみましょう。

app.py
from pinecone.grpc import PineconeGRPC

pc = PineconeGRPC(api_key="pclocal", host="http://localhost:5081")
result = pc.list_indexes()

print(result)

https://docs.pinecone.io/guides/indexes/view-index-information

空のリストが返ってきました。

takakuni:~/environment $ python app.py
[]

インデックスでも作ってみましょう。

create_index.py
from pinecone.grpc import PineconeGRPC
from pinecone import ServerlessSpec

pc = PineconeGRPC(api_key="pclocal", host="http://localhost:5081")

index_name = "pinecone-local-index"

if not pc.has_index(index_name):
  pc.create_index(
    name=index_name,
    dimension=1024,
    metric='cosine',
    spec=ServerlessSpec(
      cloud="aws",
      region="us-east-1"
    )
  )

result = pc.list_indexes()
print(result)

https://docs.pinecone.io/guides/indexes/create-an-index

上手く作成できていますね。楽にローカルでテストできるのは嬉しいですね。

takakuni:~/environment $ python create_index.py
[{
    "name": "pinecone-local-index",
    "dimension": 1024,
    "metric": "cosine",
    "host": "localhost:5082",
    "spec": {
        "serverless": {
            "cloud": "aws",
            "region": "us-east-1"
        }
    },
    "status": {
        "ready": true,
        "state": "Ready"
    },
    "deletion_protection": "disabled"
}]

埋め込み処理をしてみましょう。 GRPCClientConfig で TLS を無効にするのがポイントです。

embeddings.py
import boto3
import json
from pinecone.grpc import PineconeGRPC, GRPCClientConfig

pc = PineconeGRPC(api_key="pclocal", host="http://localhost:5081")
client = boto3.client("bedrock-runtime", region_name="us-east-1")

# 各種設定
model_id = "amazon.titan-embed-text-v2:0"
index_name = "pinecone-local-index"


input_text = "Please recommend books with a theme similar to the movie 'Inception'."
native_request = {"inputText": input_text}

# エンべディングの実行
request = json.dumps(native_request)
response = client.invoke_model(modelId=model_id, body=request)
request_id = response["ResponseMetadata"]["RequestId"]
model_response = json.loads(response["body"].read())
embedding = model_response["embedding"]

# ベクトルデータベースへの保管
host = pc.describe_index(index_name).host
index = pc.Index(host=host, grpc_config=GRPCClientConfig(secure=False))

result = index.upsert(
  vectors=[
    {
      "id": request_id,
      "values": embedding,
      "metadata": {"text": input_text}
    }
  ]
)

print(result)

https://docs.pinecone.io/guides/data/upsert-data

https://docs.aws.amazon.com/bedrock/latest/userguide/bedrock-runtime_example_bedrock-runtime_InvokeModelWithResponseStream_TitanTextEmbeddings_section.html

一件登録できたと確認できました。

takakuni:~/environment $ python embeddings.py
upserted_count: 1

最後にデータを取得してみましょう。

fetch.py
from pinecone.grpc import PineconeGRPC, GRPCClientConfig

pc = PineconeGRPC(api_key="pclocal", host="http://localhost:5081")

index_name = "pinecone-local-index"
host = pc.describe_index(index_name).host
index = pc.Index(host=host, grpc_config=GRPCClientConfig(secure=False))

for ids in index.list():
    print(index.fetch(ids))

https://docs.pinecone.io/guides/data/list-record-ids

https://docs.pinecone.io/guides/data/fetch-data

values の値は抜粋しますが、ベクトルデータが json 形式で取得できました。

{
	"namespace": "",
	"usage": {
		"read_units": 0
	},
	"vectors": {
		"b8b2d952-219f-418a-941b-73668ee29a8e": {
			"id": "b8b2d952-219f-418a-941b-73668ee29a8e",
			"metadata": {
				"text": "'Please ''recommend ''books ''with ''a ''theme ''similar ''to ''the ''movie ''Inception'."
			},
			"sparse_values": { "indices": [], "values": [] },
			"values": [-0.024926797]
		}
	}
}

まとめ

以上、「ローカルでベクトルデータベースがテストできる Pinecone Local を試してみる」でした。

エンべディングまでアプリで賄うケースで、開発スピードが向上しそうな気がしました。

このブログがどなたかの参考になれば幸いです。

AWS 事業本部コンサルティング部のたかくに(@takakuni_)でした!

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.